<script setup>
import { ref, onMounted, computed } from 'vue'

const props = defineProps({
  // 导航栏样式-背景颜色
  navStyle: {
    type: Object,
    default() {
      return {
        background: '#F8F8F8',
      }
    },
  },
  // 标题
  title: {
    type: String,
    default: '',
  },
  // 字体颜色
  titleColor: {
    type: String,
    default: '#666',
  },
  // 标题大小-rpx
  titleSize: {
    type: [String, Number],
    default: '32',
  },
  // 图标颜色-有设置就用图标颜色，否则就用字体颜色
  iconBackColor: {
    type: String,
    default: '#666',
  },
  // 图标名称
  iconBackName: {
    type: String,
    default: 'nav-back',
  },
  // 图标大小-rpx
  iconBackSize: {
    type: [String, Number],
    default: 50,
  },
  // 是否固定定位
  fixed: {
    type: Boolean,
    default: false,
  },
  // 默认导航栏高度-px
  height: {
    type: Number,
    default: 44,
  },
  // 是否显示左侧内容
  isBack: {
    type: Boolean,
    default: true,
  },
  // 自定义返回逻辑
  customBack: {
    type: Function,
    default: null,
  },
})

// 自定义事件
const emit = defineEmits(['getHeight'])

// 获取系统信息的同步接口
let deviceInfo = uni.getDeviceInfo()
let windowInfo = uni.getWindowInfo()
// 胶囊信息
let menuButtonInfo = { width: props.title ? 90 : 0 }

// 获取小程序胶囊信息
// #ifdef MP
menuButtonInfo = uni.getMenuButtonBoundingClientRect()
// #endif

// 状态栏高度
let statusBarHeight = computed(() => {
  return windowInfo.statusBarHeight
})

// 导航栏高度
let navInnerHeight = computed(() => {
  /**
   * APP-PLUS || H5 逻辑
   */
  // #ifdef APP-PLUS || H5
  return props.height
  // #endif
  /**
   * 小程序逻辑
   * (menuButtonInfo.top - statusBarHeight) * 2 + menuButtonInfo.height
   */
  // #ifdef MP
  let height = deviceInfo.platform == 'ios' ? 44 : 48
  return props.height ? props.height : height
  // #endif
})

// 自定义导航栏高度总和
let navBarHeight = computed(() => {
  return statusBarHeight.value + navInnerHeight.value
})

// 整个导航栏的样式
const navbarStyle = computed(() => {
  let style = {
    '--menu-width': `${menuButtonInfo.width + 10}px`,
  }
  // 合并用户传递的背景色对象
  Object.assign(style, props.navStyle)
  return style
})

/**
 * 返回逻辑
 */
const handleBack = () => {
  // 如果自定义了点击返回按钮的函数，则执行，否则执行返回逻辑
  if (typeof props.customBack === 'function') {
    props.customBack()
  } else uni.navigateBack()
}

const init = () => {
  emit('getHeight', navBarHeight.value, navInnerHeight.value, windowInfo)
}

onMounted(() => init())
</script>

<template>
  <view
    class="navbar"
    :class="{ 'navbar-fixed': fixed }"
    :style="[navbarStyle]"
  >
    <!-- 状态栏 -->
    <view
      class="status-bar"
      :style="{ height: `${statusBarHeight}px` }"
    ></view>
    <!-- 导航栏 -->
    <view
      class="navbar-inner"
      :class="{ 'navbar-inner-width': !title }"
      :style="{ height: `${navInnerHeight}px` }"
    >
      <!-- 返回 -->
      <view
        class="navbar-back"
        v-if="isBack"
      >
        <slot name="left">
          <u-icon
            :name="iconBackName"
            :size="iconBackSize"
            :color="iconBackColor ? iconBackColor : titleColor"
            @click="handleBack"
          ></u-icon>
        </slot>
      </view>
      <!-- 标题 -->
      <view
        class="navbar-content-title"
        v-if="title"
      >
        <view
          class="title"
          :style="{ color: titleColor, fontSize: `${titleSize}rpx` }"
        >
          {{ title }}
        </view>
      </view>
      <!-- 内容区域 -->
      <view
        class="navbar-content"
        v-if="$slots.default"
      >
        <slot></slot>
      </view>
      <!-- 右边-胶囊位置 -->
      <view class="navbar-right">
        <slot name="right"></slot>
      </view>
    </view>
  </view>
</template>

<style lang="scss" scoped>
@mixin flex($direction: row) {
  /* #ifndef APP-NVUE */
  display: flex;
  flex-direction: $direction;
  /* #endif */
}

$menuWidth: var(--menu-width);

.navbar {
  position: relative;
  width: 100%;
  &-fixed {
    position: fixed;
    top: 0;
    right: 0;
    left: 0;
    z-index: 99;
  }
}

.status-bar {
  width: 100%;
}

.navbar-inner {
  @include flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20rpx;
  position: relative;
  &-width {
    /* #ifndef APP || H5 */
    width: calc(100% - $menuWidth - 20rpx);
    /* #endif */
  }
}

.navbar-content {
  flex: auto;
  @include flex;
  justify-content: center;
}

.navbar-content-title {
  flex: 1 0 auto;
  @include flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  position: absolute;
  left: $menuWidth;
  right: $menuWidth;
  .title {
    font-size: 32rpx;
    white-space: nowrap;
    overflow: hidden;
    word-break: break-all;
    text-overflow: ellipsis;
  }
}

.navbar-back,
.navbar-right {
  flex: none;
  @include flex;
  align-items: center;
}

.navbar-back {
  padding: 14rpx;
}

.navbar-right {
  justify-content: flex-end;
}
</style>
